package jp.co.worksap.ate.gomoku.hadoopai;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import jp.co.worksap.ate.gomoku.localai.GoNode;
import jp.co.worksap.ate.gomoku.localai.GobanNode;
import jp.co.worksap.ate.gomoku.localai.LocalAIUtil;
import jp.co.worksap.ate.gomoku.localai.MultiLevelAI;
import jp.co.worksap.ate.gomoku.model.GoPoint;
import jp.co.worksap.ate.gomoku.model.GoState;
import jp.co.worksap.ate.gomoku.model.Goban;
import jp.co.worksap.ate.gomoku.model.IGomokuAI;

public abstract class AbsHadoopAI implements IGomokuAI {

	@Override
	public GoPoint nextMove(Goban goban, GoState goType, int aiLevel) {
		List<GoNode> nodeList = LocalAIUtil.getAllValueableEmptyGoNode(goban, 2);
		List<GobanNode> rootList = new ArrayList<GobanNode>();
		for(GoNode goNode : nodeList) {
			GobanNode rootNode = new GobanNode(goban.clone(), goType, goNode.getX(), goNode.getY());
			rootList.add(rootNode);
		}
		MultiLevelAI.cutChild(rootList);
		double max = -Double.MAX_VALUE;
		int level = aiLevel * 2 -1;
		nodeList.clear();
		Map<String, String> map;
		try {
			String folderName = getFolderName();
			map = computeScoreMap(folderName, goban, goType, rootList, level);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		int nodeNum = 0;
		for(GobanNode rootNode : rootList) {
			GoNode goNode = new GoNode(rootNode.getX(), rootNode.getY());
			String key = goNode.getX()+"_"+goNode.getY();
			String resultStr = map.get(key);
			String[] parts = resultStr.split("_");
			double score = Double.parseDouble(parts[0]);
			nodeNum += Integer.parseInt(parts[1]);
			goNode.setScore(score);
			nodeList.add(goNode);
			if(score > max) {
				max = score;
			}
		}
		List<GoNode> maxList = new ArrayList<GoNode>();
		for(GoNode node : nodeList) {
			if(Math.abs(max - node.getScore())<(Math.abs(max)/10)) {
				maxList.add(node);
			}
		}
		GoNode node;
		if(maxList.size()==1) {
			node = maxList.get(0);
		} else {
			Random r = new Random();
			node = maxList.get(r.nextInt(maxList.size()));
		}
		GoPoint resultPoint = new GoPoint(node.getX(), node.getY());
		resultPoint.setNodeNum(nodeNum);
		return resultPoint;
	}
	private String getFolderName() {
		Random r = new Random();
		String name = ""+System.currentTimeMillis()+r.nextInt(100000);
		return name;
	}
	protected abstract Map<String, String> computeScoreMap(String folderName, Goban goban, GoState goType, List<GobanNode> rootList, int level);
}
